﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;

namespace Elderos.Utils.Web
{
	public static class WebRequest
	{
		/// <summary>
		/// Запрос "Get"
		/// </summary>
		/// <param name="uri"></param>
		/// <param name="processDelay"></param>
		/// <returns></returns>
		public static WebArgs Get(Uri uri, TimeSpan processDelay)
		{
			HttpWebRequest request = GetRequest(uri, "GET");
			return GetResponse(request, processDelay);
		}

		/// <summary>
		/// Запрос "POST"
		/// </summary>
		/// <param name="uri"></param>
		/// <param name="processDelay"></param>
		/// <param name="data"></param>
		/// <returns></returns>
		public static WebArgs Post(Uri uri, TimeSpan processDelay, string data)
		{
			HttpWebRequest request = GetRequest(uri, "POST");
			if (data.Length > 0)
			{
				using (var writer = new StreamWriter(request.GetRequestStream()))
					writer.Write(data);
			}
			return GetResponse(request, processDelay);
		}

		private static WebArgs GetResponse(HttpWebRequest request, TimeSpan processDelay)
		{
			Thread.Sleep(processDelay);
			HttpWebResponse response;
			try
			{
				response = (HttpWebResponse)request.GetResponse();
			}
			catch (WebException ex)
			{
				response = (HttpWebResponse)ex.Response;
			}

			if (response == null)
				throw new WebException("Response was not received");

			List<byte> responseBytes = response.ContentLength > 0
										   ? new List<byte>((int)response.ContentLength)
										   : new List<byte>();


			using (Stream responseStream = response.GetResponseStream())
			{
				var buffer = new byte[10240];
				int bytesRead;
				do
				{
					bytesRead = responseStream.Read(buffer, 0, buffer.Length);
					responseBytes.AddRange(buffer);
					if (bytesRead >= buffer.Length) continue;
					int delta = buffer.Length - bytesRead;
					responseBytes.RemoveRange(responseBytes.Count - delta, delta);
				} while (bytesRead != 0);
			}
			return new WebArgs(responseBytes.ToArray(), GetEncoding(response));
		}

		private static Encoding GetEncoding(HttpWebResponse response)
		{
			var rgx = new Regex("charset=(?<charset>[^;'\">]+)");
			Match match = rgx.Match(response.ContentType);
			if (match.Length > 0)
				return Encoding.GetEncoding(match.Groups["charset"].ToString());
			return null;
		}

		private static HttpWebRequest GetRequest(Uri uri, string webmethod)
		{
			var request = (HttpWebRequest)System.Net.WebRequest.Create(uri);
			request.Method = webmethod;
			return request;
		}
	}
}